﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace WFL.Windows.Forms.Theme
{
    public abstract class SkinBase
    {
        protected IDictionary<string, Style> Styles;

        public SkinBase()
        {
            
        }

        public abstract IList<SkinItem> GetList();

        protected abstract void LoadStyles(string id);

        public void Load(string id)
        {
            LoadStyles(id);
            if (Styles != null
                && Styles.Count > 0)
            {
                foreach (Style style in Styles.Values)
                {
                    style.Skin = this;
                }
            }
        }

        public Style GetStyle(string name)
        {
            if (Styles == null
                || !Styles.ContainsKey(name))
            {
                return null;
            }
            else
            {
                return Styles[name];
            }
        }


        #region 类型转换

        protected internal virtual bool ChangeType(string value, Type targetType, out object result)
        {
            result = null;
            bool succeeded = false;

            if (targetType == typeof(string))
            {
                result = value;
                succeeded = true;
            }
            else if ((targetType.IsPrimitive && targetType != typeof(IntPtr))
                || targetType == typeof(decimal)
                || targetType == typeof(DateTime))
            {
                try
                {
                    //基元类型，则调用系统转换方法
                    result = Convert.ChangeType(value, targetType);
                    succeeded = true;
                }
                catch { }
            }
            else if (targetType.IsEnum)
            {
                //枚举类型
                succeeded = ToEnum(value, targetType, out result);
            }
            else if (targetType == typeof(Color))
            {
                Color color;
                succeeded = ToColor(value, out color);
                if (succeeded)
                {
                    result = color;
                }
            }
            else if (targetType == typeof(bool))
            {
                bool b;
                succeeded = ToBoolean(value, out b);
                if (succeeded)
                {
                    result = b;
                }
            }
            else if (targetType == typeof(Point))
            {
                Point point;
                succeeded = ToPoint(value, out point);
                if (succeeded)
                {
                    result = point;
                }
            }
            else if (targetType == typeof(Size))
            {
                Size size;
                succeeded = ToSize(value, out size);
                if (succeeded)
                {
                    result = size;
                }
            }
            else if (targetType == typeof(Font))
            {
                Font font = null;
                succeeded = ToFont(value, out font);
                if (succeeded)
                {
                    result = font;
                }
            }
            else if (targetType == typeof(Padding))
            {
                Padding padding;
                succeeded = ToPadding(value, out padding);
                if (succeeded)
                {
                    result = padding;
                }
            }
            else
            {
                //无法转换，不做处理
            }
            return succeeded;
        }

        private bool ToBoolean(string value, out bool result)
        {
            result = false;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            if (IsNumber(value))
            {
                result = (Convert.ToInt32(value) != 0);
                return true;
            }
            else
            {
                result = Convert.ToBoolean(value);
                return true;
            }
        }

        private bool ToColor(string value, out Color result)
        {
            result = Color.Empty;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            int argb = -1;
            if (int.TryParse(value, System.Globalization.NumberStyles.AllowHexSpecifier, null, out argb))
            {
                argb = (int)((uint)argb | 0xff000000u);
                result = Color.FromArgb(argb);
                return true;
            }

            return false;
        }

        private bool ToPoint(string value, out Point result)
        {
            result = Point.Empty;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            string[] xy = value.Split(',');
            if (xy.Length == 2)
            {
                int x = 0;
                int y = 0;
                if (int.TryParse(xy[0], out x)
                    && int.TryParse(xy[1], out y))
                {
                    result = new Point(x, y);
                    return true;
                }
            }

            return false;
        }

        private bool ToSize(string value, out Size result)
        {
            result = Size.Empty;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            string[] wh = value.Split(',');
            if (wh.Length == 2)
            {
                int w = 0;
                int h = 0;
                if (int.TryParse(wh[0], out w)
                    && int.TryParse(wh[1], out h))
                {
                    result = new Size(w, h);
                    return true;
                }
            }

            return false;
        }

        private bool ToFont(string value, out Font result)
        {
            result = null;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            string[] fs = value.Split(',');
            if (fs.Length == 3)
            {
                float emSize = 0;
                if (float.TryParse(fs[1], out emSize))
                {
                    FontStyle style = (FontStyle)Enum.Parse(typeof(FontStyle), fs[2]);
                    result = new Font(fs[0], emSize, style);
                    return true;
                }
            }

            return false;
        }

        private bool ToPadding(string value, out Padding result)
        {
            result = Padding.Empty;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            string[] ps = value.Split(',');
            if (ps.Length == 1)
            {
                int all = 0;
                if (int.TryParse(ps[0], out all))
                {
                    result.Left = all;
                    result.Top = all;
                    result.Right = all;
                    result.Bottom = all;
                }
                return true;
            }
            else if (ps.Length == 4)
            {
                int left = 0, top = 0, right = 0, bottom = 0;
                if (int.TryParse(ps[0], out left) &&
                    int.TryParse(ps[1], out top) &&
                    int.TryParse(ps[2], out right) &&
                    int.TryParse(ps[3], out bottom))
                {
                    result.Left = left;
                    result.Top = top;
                    result.Right = right;
                    result.Bottom = bottom;
                }
                return true;
            }

            return false;
        }

        private bool ToEnum(string value, Type enumType, out object result)
        {
            result = null;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            Type underlyingType = Enum.GetUnderlyingType(enumType);
            if (IsNumber(value))
            {
                //将整数转换为当前枚举类型的基类型，再转换为枚举
                object obj = Convert.ChangeType(value, underlyingType);
                result = Enum.ToObject(enumType, obj);
                return true;
            }
            else
            {
                string[] enumStrs = value.Split(',');
                if (underlyingType == typeof(ulong))
                {
                    ulong enumValue = 0;
                    for (int i = 0; i < enumStrs.Length; i++)
                    {
                        string enumStr = enumStrs[i];

                        ulong tp = Convert.ToUInt64(Enum.Parse(enumType, enumStr));
                        enumValue |= tp;
                    }
                    result = Enum.ToObject(enumType, enumValue);
                }
                else
                {
                    //将所有基类型为非ulong的枚举转换为等价的long类型（无损转换），再转换为枚举
                    long enumValue = 0;
                    for (int i = 0; i < enumStrs.Length; i++)
                    {
                        string enumStr = enumStrs[i];

                        long tp = Convert.ToInt64(Enum.Parse(enumType, enumStr));
                        enumValue |= tp;
                    }
                    result = Enum.ToObject(enumType, enumValue);
                }
                return true;
            }
        }

        private bool IsNumber(string value)
        {
            //暂时仅支持十进制整数表示形式(不带符号)
            return Regex.IsMatch(value, @"\d+");
        }

        #endregion


    }
}
